﻿namespace NTLib.Core.Descriptors
{
    using System;

    /// <summary>
    /// Class used to define element represent by an id with a name to be use in debug.
    /// </summary>
    public class Descriptor : IDescriptor, IEquatable<IDescriptor>
    {
        #region Fields

        private readonly string _name;

        #endregion

        #region CTOR

        /// <summary>
        /// Initializes a new instance of the <see cref="Descriptor"/> class.
        /// </summary>
        /// <param name="id">The identifier.</param>
        /// <param name="name">The name.</param>
        public Descriptor(Guid id, string name = null)
        {
            this.Id = id;
            this._name = name;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the identifier associate to the descriptor.
        /// </summary>
        public Guid Id { get; }

        /// <summary>
        /// Gets the name of the descriptor.
        /// </summary>
        public virtual string Name
        {
            get { return this._name; }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Clones this instance.
        /// </summary>
        public virtual IDescriptor Clone()
        {
            var newInstance = CreateCloneNewInstance();

            FullFillCloneInstance(newInstance);

            return newInstance;
        }

        /// <summary>
        /// Equalses the specified other.
        /// </summary>
        public bool Equals(IDescriptor other)
        {
            if (object.ReferenceEquals(other, this))
            {
                return true;
            }

            if (object.Equals(other, null) ||
                this.GetType() != other.GetType() ||
                other.Id != this.Id ||
                !string.Equals(other.Name, this.Name, StringComparison.CurrentCultureIgnoreCase))
            {
                return false;
            }

            return OnEquals(other);
        }

        /// <summary>
        /// Called when the <see cref="Equals(IDescriptor)"/> method is called.
        /// All the basic check have already been check when the <see cref="OnEquals(IDescriptor)"/>
        /// is called.
        /// </summary>
        protected virtual bool OnEquals(IDescriptor other)
        {
            return true;
        }

        /// <summary>
        /// Creates the new clone instance.
        /// </summary>
        protected virtual IDescriptor CreateCloneNewInstance()
        {
            return new Descriptor(this.Id, this.Name);
        }

        /// <summary>
        /// Fulls the fill clone instance.
        /// </summary>
        protected virtual void FullFillCloneInstance(IDescriptor clone)
        {
        }

        #endregion
    }
}
